﻿using VueEleAdminFurion.Controllers.UserService.Dto;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;
using Furion;
using System.Security.Claims;
using SqlSugar;
using Furion.DataEncryption;
using VueEleAdminFurion.Model;

namespace VueEleAdminFurion.Controllers.UserService;

[DynamicApiController]
public class UserService
{
    SqlSugar.ISqlSugarClient db;
    public UserService(ISqlSugarClient db)
    {
        this.db = db;
    }

    [Microsoft.AspNetCore.Authorization.AllowAnonymous]
    public async ValueTask<string> Loginin([Microsoft.AspNetCore.Mvc.FromBody] Dto.UserDto dto)
    {
        try
        {
            Guid? subjectId = null;
            var lowUserName = dto.UserName.ToLower();
            var encPassWord = DESEncryptExtension.Encrypt(dto.PassWord);
            var user = db.Queryable<User>().Where(it => it.UserName.Equals(lowUserName) && it.PassWord.Equals(encPassWord)).First();

            if (user is null)
            {
                throw new Exception("The user name or password is not correct!");
            }
            else
            {
                subjectId = user.Id;
            }

            // 生成 token
            var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>()
            {
                { "UserId", user.Id },  // 存储Id
                { "Account",user.UserName }, // 存储用户名
            }, 24 * 60);
            return accessToken;
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }

    public async ValueTask<UserInfoDto> GetUserInfo()
    {
        try
        {
            var userId = Guid.Parse(input: App.User?.FindFirstValue("UserId"));
            var userName = App.User?.FindFirstValue("Account");
            var roles = db.Queryable<UserRole>()
                .LeftJoin<Role>((ur, r) => ur.RoleId == r.Id)
                .Where(ur => ur.UserId == userId)
                .Select((ur, r) => r.RoleName)
                .ToList();

            //获取用户关联角色权限
            var perRoles = db.Queryable<UserRole>()
                .LeftJoin<Role>((ur, ro) => ur.RoleId == ro.Id)
                .LeftJoin<RolePermissions>((ur, ro, rp) => ro.Id == rp.RoleId)
                .LeftJoin<Permissions>((ur, ro, rp, p) => p.Id == rp.PermissionsId)
                .Where(ur => ur.UserId == userId)
                .Select((ur, ro, rp, p) => p);

            //获取独立设置用户权限
            var perUser = db.Queryable<UserPermissions>()
                .LeftJoin<Permissions>((ur, p) => ur.PermissionsId == p.Id)
                .Where(ur => ur.UserId == userId)
                .Select((ur, p) => p);
            
            //合并权限
            var pers = db.UnionAll(perRoles, perUser).Distinct().ToList();

            var npers = new List<Permissions>();

            //获取权限列表
            var permissionss = new List<string>();

            //递归出全部上级
            foreach (var per in pers)
            {
                treePar(per);
            }

            //递归，主要区分出拥有的权限  和菜单列表
            void treePar(Permissions per)
            {
                if (!npers.Exists(x => x.PermissionsCode == per.PermissionsCode) && per.AlwaysShow)
                    npers.Add(per);

                if (!permissionss.Exists(x => x == per.PermissionsCode) && !string.IsNullOrWhiteSpace(per.PermissionsCode))
                    permissionss.Add(per.PermissionsCode);

                if (per.ParentId != null)
                {
                    if (pers.Find(x => x.Id == per.ParentId) is Permissions permissions)
                    {
                        treePar(permissions);
                    }
                    else
                    {
                        var p = db.Queryable<Permissions>().Where(it => it.Id == per.ParentId).First();
                        treePar(p);
                    }                    
                }
            }


            var user = db.Queryable<User>().Where(it => it.Id == userId).First();

            var outPut = new UserInfoDto();
            outPut.Id = user.Id;
            outPut.UserName = user.UserName;
            outPut.Phone = user.Phone;
            outPut.EmailAddress = user.EmailAddress;
            outPut.Roles = roles;
            outPut.PermissionsMenus = npers;
            outPut.Permissionss = permissionss;

            return outPut;
        }
        catch (Exception ex) { throw new Exception(ex.Message); }
    }

    [HttpPost]
    public async ValueTask Logout() => await ValueTask.CompletedTask;


    public async ValueTask DeleteUser([FromQuery] User dto)
    {
        db.Deleteable(dto).ExecuteCommand();
        db.Deleteable<UserRole>().Where(it => it.UserId == dto.Id).ExecuteCommand();
        db.Deleteable<UserPermissions>().Where(it => it.UserId == dto.Id).ExecuteCommand();
    }


    public async ValueTask CreateUser(UserDto dto)
    {
        dto.Id = Guid.NewGuid();
        dto.CreateUserId = Guid.Parse(input: App.User?.FindFirstValue("UserId"));
        dto.CreateTime = db.GetDate().ToString();
        dto.UpdateTime = db.GetDate().ToString();
        dto.PassWord= DESEncryptExtension.Encrypt(dto.PassWord);
        var ss = db.Insertable<User>(dto).IgnoreColumns(it => new { it.TimeStamp }).IgnoreColumns(ignoreNullColumn: true).ExecuteCommand();

        if (dto.PermissionsIds.Any())
        {
            db.Deleteable<UserPermissions>().Where(it => it.UserId == dto.Id).ExecuteCommand();
            dto.PermissionsIds.ForEach(x =>
                db.Insertable(new UserPermissions()
                {
                    PermissionsId = x,
                    UserId = dto.Id,
                    Id = Guid.NewGuid(),
                }).IgnoreColumns(it => it.TimeStamp).IgnoreColumns(ignoreNullColumn: true).ExecuteCommand()
            );
        }

        if (dto.RoleIds.Any())
        {
            db.Deleteable<UserRole>().Where(it => it.UserId == dto.Id).ExecuteCommand();
            dto.RoleIds.ForEach(x =>
                db.Insertable(new UserRole()
                {
                    RoleId = x,
                    UserId = dto.Id,
                    Id = Guid.NewGuid(),
                }).IgnoreColumns(it => it.TimeStamp).IgnoreColumns(ignoreNullColumn: true).ExecuteCommand()
            );
        }
    }

    public async ValueTask UpdateUser(UserDto dto)
    {
        var ss = db.Updateable<User>(dto).IgnoreColumns(it => new { it.CreateTime, it.TimeStamp }).IgnoreColumns(ignoreAllNullColumns: true).ExecuteCommand();

        if (dto.PermissionsIds.Any())
        {
            db.Deleteable<UserPermissions>().Where(it => it.UserId == dto.Id).ExecuteCommand();
            dto.PermissionsIds.ForEach(x =>
                db.Insertable(new UserPermissions()
                {
                    PermissionsId = x,
                    UserId = dto.Id,
                    Id = Guid.NewGuid(),
                }).IgnoreColumns(it => it.TimeStamp).IgnoreColumns(ignoreNullColumn: true).ExecuteCommand()
            );
        }

        if (dto.RoleIds.Any())
        {
            db.Deleteable<UserRole>().Where(it => it.UserId == dto.Id).ExecuteCommand();
            dto.RoleIds.ForEach(x =>
                db.Insertable(new UserRole()
                {
                    RoleId = x,
                    UserId = dto.Id,
                    Id = Guid.NewGuid(),
                }).IgnoreColumns(it => it.TimeStamp).IgnoreColumns(ignoreNullColumn: true).ExecuteCommand()
            );
        }
    }



    public async ValueTask<dynamic> GetUserByPage([FromQuery] UserByPage dto)
    {
        try
        {
            int totalCount = 0;
            var sss = db.Queryable<UserDto>().ToSqlString();

            var users = db.Queryable<UserDto>().ToPageList(dto.PageIndex, dto.PageSize, ref totalCount).Where(it => it.UserName.Contains(dto.username ?? "") && it.EmailAddress.Contains(dto.emailaddress ?? "") && it.Phone.Contains(dto.phone ?? "")).ToList();

            foreach (var user in users)
            {
                //获取角色权限
                var roles = db.Queryable<UserRole>()
                    .LeftJoin<Role>((ur, ro) => ur.RoleId == ro.Id)
                    .Where(ur => ur.UserId == user.Id);

                user.RoleIds = roles.Select((ur, ro) => ro.Id).ToList();
                user.RoleNames = string.Join(";", roles.Select((ur, ro) => ro.RoleName).ToList());
            }


            return new { total = totalCount, data = users };

        }
        catch (Exception ex) { throw new Exception(ex.Message); }
    }

    public async ValueTask<List<Guid>> GetUserPermissionsIds([FromQuery] Guid id)
    {
        return db.Queryable<UserPermissions>().Where(it => it.UserId == id).Select(it => it.PermissionsId).ToList();
    }

    public async ValueTask<List<Guid>> GetUserRoleIds([FromQuery] Guid id)
    {
        return db.Queryable<UserRole>().Where(it => it.UserId == id).Select(it => it.RoleId).ToList();
    }
}